class Stopwatch
  def tick
    @tick = Time.now
  end
  
  def tock
    Time.now - @tick
  end
end

require 'rudoku'
include Rudoku

require 'rules'
require 'field_selectors'
require 'candidate_selectors'

$debug = true
$enable_color = true # disable this on windows, it uses unix-y escape codes

metro = "--38----4-7--5461-2----7-5-9-532-7------8593-6--49----7--6---8--26-1----4-----1-2"
manna_symmetrisch = "7-42-13-5---------3--5-7--26-5---8-3----7----4-3---9-72--9-5--1---------5-97-36-4"
manna_tiseenacht = "2--81--46---6--1--1-7----2-------261-2-9-3-5-654-------1----6-4--3--6---48--79--5"
qassim_hamza = "---7--8------4--3------9--16--5------1--3--4---5--1--75--2--6---3--8--9---7-----2"
two_string_kite = "000400100000705032032000700001080605070000020503010800008000560650803000007001000"
wc_bruteforce = "000000000000003085001020000000507000004000100090000000500000073002010000000040009"
jf1 = "100000002090400050006000700050903000000070000000850040700000600030009080002000001" # this is the Easter Monster
jf2 = "020000600000100000700030050008040903300000008000020406630500000005009002010084000"
jf3 = "708000300000201000500000000040000026300080000000100090090600004000070500000000000"
jf4 = "850002400720000009004000000000107002305000900040000000000080070017000000000036040"
jf5 = "100050000006009000080200004040030008007000060900000100030800002000004050000010700"
jf6 = "400009000030010020006700000001000004050200070800000600000004008070030010000500900"
swordfish = "000308002000040700001970080905003006037000520800500903070096100006030000400807000"

su = Sudoku.from_str(manna_symmetrisch)
# su = Sudoku.new # leeg!

puts su.to_s
puts "Empty fields: #{su.count_empty}"
puts "Consistent: #{su.consistent?}"

puts "\n\n>> SOLVING...\n"

so = Solver.new [HiddenSingle, DirectElimination, LockedCandidatesPointing, NakedPair, XWing, Swordfish], UberFieldSelector, UberCandidateSelector

# probably the optimal solver for jf3 at the moment, HiddenPair is important apparently!
# so = Solver.new [HiddenSingle, DirectElimination, LockedCandidatesPointing, HiddenPair], HiddenFieldSelector, UberCandidateSelector

# this solver proves that scanning makes LC checking obsolete (VERY VERY SLOW!)
# so = Solver.new [Scanning, LockedCandidatesPointing, LockedCandidatesClaiming]

# this solver is a bruteforcer.
# so = Solver.new [], UberFieldSelector, UberCandidateSelector

use_force = true
# so.dynamic_priorities = true

puts "   - RULES: " + so.rules.collect { |r| r.name }.join(", ")
puts "   - FIELD SELECTOR: #{so.field_selector.name}"
puts "   - CANDIDATE SELECTOR: #{so.candidate_selector.name}"
puts "   - USING FORCE: #{use_force}"
puts "   - DYNAMIC PRIORITIES" if so.dynamic_priorities

puts "\n\n"

t = Stopwatch.new
t.tick
so.solve(su, use_force)
duration = t.tock

if su.solved?
  puts "\n\n>> SOLVED!\n"
else
  puts "\n\n>> FAILED :(\n"
end

puts "\n\n" + su.to_s + "\n\n"
puts "Empty fields: #{su.count_empty}"
puts "Consistent: #{su.consistent?}"

puts "Duration: #{duration}s\n\n"
puts "#{so.ara} attempted rule applications"
puts "#{so.sra} succesful rule applications"
puts "#{so.guess_count} attempted guesses"
puts "#{su.count_guessed} correct guesses"
puts "#{so.ara_rp} attempted rule applications on the correct search path"
puts "#{so.sra_rp} succesful rule applications on the correct search path"

puts "\n\n"

so.rules.each do |rule|
  puts rule.name.upcase
  puts " - #{so.stats[rule].ara} attempted applications"
  puts " - #{so.stats[rule].sra} successful applications"
  puts "\n"
end
